package com.dd.edu.rabbitmqboot.business;

import com.alibaba.fastjson.JSONObject;
import com.dd.edu.rabbitmqboot.model.Order;
import com.dd.edu.rabbitmqboot.model.OrderDB;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.GetResponse;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 支付控制器
 */
@Controller
@RequestMapping("/pay")
public class PayController {

    @Autowired
    CachingConnectionFactory factory;

    @RequestMapping("/{orderNo}")
    @ResponseBody
    public String pay(@PathVariable("orderNo") String orderNo){

        final Order order = OrderDB.orderMap.get(orderNo);
        // 从mq中拉取支付信息，确认支付状态
        if (order.getOrderStatus().equals(Order.STATUS_WAIT_PAY)) {
            final Connection connection = factory.createConnection();
            try(final Channel channel = connection.createChannel(true)){
                // 主动拉取消息： 从队列； 指定是否自动确认消息
                final GetResponse getResponse = channel.basicGet("q.order.ttl", true);
//                需要注意的 basicAck 方法需要传递两个参数
//                deliveryTag（唯一标识 ID）：当一个消费者向 RabbitMQ 注册后，会建立起一个 Channel ，RabbitMQ 会用 basic.deliver 方法向消费者推送消息，这个方法携带了一个 delivery tag， 它代表了 RabbitMQ 向该 Channel 投递的这条消息的唯一标识 ID，是一个单调递增的正整数，delivery tag 的范围仅限于 Channel
//                multiple：为了减少网络流量，手动确认可以被批处理，当该参数为 true 时，则可以一次性确认 delivery_tag 小于等于传入值的所有消息
                channel.basicAck(getResponse.getEnvelope().getDeliveryTag(),false);

                // 更新订单状态
                order.setOrderStatus(Order.STATUS_PAY_SUCCESS);
                OrderDB.orderMap.put(orderNo, order);
            } catch (Exception e){
                e.printStackTrace();
            } finally {
                if (connection.isOpen()){
                    connection.close();
                }
            }


            return "支付成功";
        } else if (order.getOrderStatus().equals(Order.STATUS_PAY_SUCCESS)) {
            return "支付已支付成功，请勿重复支付";
        } else {
            return "订单已超时";
        }

    }



    /**
     * 监听订单死信队列消息
     */
    @RabbitListener(queues = "q.order.dlx")
    public void dixLinseed(String message){
        System.out.println(message);
        try {
            final Order order = JSONObject.parseObject(message, Order.class);
            if (order.getOrderStatus().equals(Order.STATUS_WAIT_PAY)) {
                order.setOrderStatus(Order.STATUS_TIMEOUT);
                OrderDB.orderMap.put(order.getOrderNo(), order);
                System.out.println("订单支付超时：" + order.getOrderNo());
            } else if (order.getOrderStatus().equals(Order.STATUS_PAY_SUCCESS)) {
                System.out.println("订单已支付成功，死信队列监听处理。。。跳过");
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

}
